using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Timeline;
using static VActInput;
/// <summary>
/// 这里是之前文件的备份
/// </summary>
public class VActInput : MonoBehaviour
{
    //TODO:这里需要追踪流的流向 
    //规则表, 键位对动作的绑定
    [LabelText("接受设备输入")] public bool MapperInputEnable = true;
    [LabelText("接受语音输入")] public bool audioInputEnable = false;
    public List<VInputToActMapper> MapperList;
    [ReadOnly] public List<VAct> vActs = new();
    private VActProcessor processor; //这里也不应该暴露在外, 所有的操作都得过Input 的手
    public List<VVacancyActMapper> vacancyFliter;
    [LabelText("输入重载")]
    [SerializeReference]
    public VInputOverride inputOverride;
    public void Init(VActProcessor processor)
    {
        this.processor = processor;
        if (inputOverride == null) Reset();
        inputOverride.InitLoader(ips, this);
        MapperList = inputOverride.GenMapperList();

        RegisteKeyToInput();
        RegisteProcessorCallback();
        if (MapperList != null)
            foreach (var r in MapperList)
            {
                r.Init(this);
            }

        //单走一个语音输入
        if (audioInputEnable)
        {
            var talk = ips.FindAction("T");
            talk.performed += (e) =>
            {
                VAudio.StartRecordOffline();
            };
            talk.canceled += (e) =>
            {
                VAudio.StopRecordOffline();
            };
            var wall = ips.FindAction("Check");
            inputOverride.LoadAudioOverride(processor);
        }
    }
    private void Reset()
    {
        inputOverride = new VInputOverride();
    }
    protected virtual void RegisteProcessorCallback()
    {
        curDoingAct = VAct.emptyAct;
        // processor.onTransDefault += () =>
        // {
        //     curDoingAct = VAct.emptyAct;
        // };

        processor.onEnterVacancyStringArgs += (args) =>
        {
            vacancyFliter = args;
        };

        processor.onEnterNewAct += _ =>
        {
            vacancyFliter = null;
            // ResetTransform(); // 先默认复原位置
        };

        processor.onAskEnterAct += ForceDoAct;

    }
    protected VAct FindAct(string name)
    {
        return vActs.Find(x => x.name == name);
    }

    protected virtual void RegisteKeyToInput()
    {
        foreach (var mapper in MapperList)
        {
            if (mapper == null) continue;
            var ip = mapper.oriKey;
            ip.performed += mapper.MapperDoAct;
        }
    }
    public VAct curDoingAct;
    public VAct doingAct
    {
        get => curDoingAct == VAct.emptyAct ? null : curDoingAct;
        set => curDoingAct = value;
    }
    public bool AskActPermission(VAct act)
    {
        //过滤器的权限是更高的
        if (ProcessVacancyFliter(act)) return true;
        //Priority排序
        if (act == null || curDoingAct.priority > act.priority) return false;
        else
        {
            processor.onEnterNewAct(curDoingAct);
            curDoingAct = act;
            //先放在这个地方处理位置记录问题
            RecordTransform();
            return true;
        }
    }
    public bool ProcessVacancyFliter(VAct act)
    {
        //这里bool值表示是否已经有结果,有结果则无需后续判断
        if (vacancyFliter == null || vacancyFliter.Count == 0) return false; // 无设定 or 允许所有输入
        var mapper = vacancyFliter.Find(x => x.oriAct == act.name);
        if (mapper != null)
        {
            if (!string.IsNullOrEmpty(mapper.mapAct))
            {
                var mapAct = FindAct(mapper.mapAct);
                if (mapAct != null) act = mapAct;
            }
            processor.onEnterNewAct(curDoingAct);
            curDoingAct = act;
            return true;
        }
        return false;
    }
    public void ForceDoAct(string actName)
    {
        var act = vActs.Find(x => x.name == actName);
        if (act == null) Debug.Log("未找到Act:" + actName);
        if (AskActPermission(act)) DoCurAct();
    }
    private Vector3 rPosition;
    private Quaternion rRotation;
    private void RecordTransform()
    {
        rPosition = transform.position;
        rRotation = transform.rotation;
    }
    private void ResetTransform()
    {
        // transform.position = rPosition;
        transform.DoTween(transform.position, rPosition);
        transform.rotation = rRotation;
    }
    public void DoCurAct()
    {
        if (curDoingAct.actObserver is not FlowObserver) curDoingAct.actObserver.Subscribe();
    }


    #region InputSystem Life
    public void AddAct(string aname, Observer ob, int type, int pri = 10) => vActs.Add(new VAct(aname, ob, type, pri));
    public void AddAct(Observer ob) => vActs.Add(new VAct(ob));
    public void AddAct(string aname, Observer ob, int pri) => vActs.Add(new VAct(aname, ob, -1, pri));
    public bool ExistAct(string aname) => vActs.Find(x => x.name == aname) != null;
    public VInputSample ips;
    private void OnEnable()
    {
        ips = new VInputSample();
        ips.Enable();
    }
    private void OnDisable()
    {
        ips.Disable();
    }
    #endregion
}
[Serializable]
public class VAct
{
    [HorizontalGroup]
    public string name;
    [HorizontalGroup]
    public int priority;
    [HorizontalGroup]
    public int actType; // 0是state 1是skill -1表示未定义
    public Observer actObserver;
    public VAct(string aname, Observer ob, int type, int pri = 10)
    {
        name = aname;
        actObserver = ob;
        actType = type;
        priority = pri;
    }
    public VAct(Observer ob)
    {
        name = ob.name;
        actObserver = ob;
        priority = 10;
    }

    public override string ToString()
    {
        return $"{name}:priority = {priority}";
    }

    public static readonly VAct emptyAct = new VAct("empty", null, -1, 0);
}

public class VInputToActMapper
{
    public VActInput belongsto;
    public InputAction oriKey;
    public VAct oriAct;
    public List<InputAction> mKeys;
    public List<VAct> mActs;

    public bool hasModify => mKeys != null;
    //TODO:得加一个优先级排序,内部用Act不用Observer
    public void Init(VActInput input)
    {
        belongsto = input;
        if (hasModify)
            for (int i = 0; i < mKeys.Count; i++)
            {
                VAct curAct = mActs[i];
                string observerTag = $"{belongsto.gameObject.name}_{curAct.name}:use ModifyInput";  //这个应该是仅限调试信息,release看不到
                curAct.actObserver.name = observerTag;
                if (mActs[i].actObserver is FlowObserver flow)
                {
                    InputAction ip = mKeys[i];
                    flow.flowin = () =>
                    {
                        return oriKey.inProgress &&
                          ip.inProgress &&
                          belongsto.MapperInputEnable &&
                          belongsto.AskActPermission(curAct);
                    };
                    flow.Subscribe();
                }
            }
        if (oriAct == null) return;
        if (oriAct.actObserver is FlowObserver mainFlow)
        {
            string observerTag = $"{belongsto.gameObject.name}_{oriAct.name}:use OriginalInput";
            oriAct.actObserver.name = observerTag;
            mainFlow.flowin = () =>
            {
                return oriKey.inProgress &&
                SelectIndex() == -1 &&
                belongsto.MapperInputEnable &&
                belongsto.AskActPermission(oriAct);
            };
            mainFlow.Subscribe();
        }
    }
            // 这里其实问题挺多的, flowin的监测应该是frame级别的,  但是实际的调用却应该是tick级别 , 但是不对, flow中是按照恒定流走的

    public VAct ActSelect()
    {
        if (hasModify)
            for (int i = 0; i < mKeys.Count; i++)
            {
                if (mKeys[i].inProgress) return mActs[i];
            }
        return oriAct;
    }
    public void MapperDoAct(InputAction.CallbackContext ctx)
    {
        if (!belongsto.MapperInputEnable) return;
        var act = ActSelect();
        if (belongsto.AskActPermission(act)) belongsto.DoCurAct();
    }
    public int SelectIndex()
    {
        if (hasModify)
            for (int i = 0; i < mKeys.Count; i++)
            {
                if (mKeys[i].inProgress) return i;
            }
        return -1;
    }
    public bool GetModify(int index, out InputAction ip, out VAct act)
    {
        if (index != -1)
        {
            ip = mKeys[index];
            act = mActs[index];
            return true;
        }
        else
        {
            ip = null;
            act = null;
            return false;
        }
    }
    public bool GetInProgress(int index)
    {
        if (index != -1)
        {
            return oriKey.inProgress && mKeys[index].inProgress;
        }
        else
        {
            return oriKey.inProgress;
        }
    }
}

[Serializable]
public class VVacancyActMapper
{
    public string oriAct;
    public string mapAct;
}
[Serializable]
public class VInputUnit
{
    public string oriKey;
    public string oriAct;
    [HorizontalGroup("line")]
    public List<string> modifyKeys;

    [HorizontalGroup("line")]
    public List<string> modifyActs;
}

